在上篇文章我們說了「符號解析」,符號解析的任務就是:建立定義與引用之間的關聯,而「重定址」的任務就是:把程式碼中每一個符號引用和正好一個符號定義關聯起來。
當程序編譯完成後,組譯產生二進制的可重定址文件,產生的文件包含兩個 Section (上一節有說明)
這兩個 Scetion 中 包含了程式碼的重定址項(Relocation entries),其資料結構如下
typedef struct
{
Elf64_Addr r_offset; /* Address of reference */
Elf64_Xword r_info; /* Symbol index and type of relocation */
} Elf64_Rel;
typedef struct
{
Elf64_Addr r_offset; /* Address of reference */
Elf64_Xword r_info; /* Symbol index and type of relocation */
Elf64_Sxword r_addend; /* Constant part of expression */
} Elf64_Rela
在重定址階段,載入器(loader)遍歷所有重定址項並寫入每個 r_offset 指定的位置,視r_info情況選擇 Elf64_Rel 和 Elf64_Rela,Elf64_Rel 的符號位址由 r_info 獲得,Elf64_Rela 需從r_info選擇計算公式加 r_addend 獲得。
※比如說,${F}$ 中有一個未解析符號 ${K}$,如果 ${D}$ 中存在對它的定義,那麼就可以建立聯繫。如果沒有就放入 ${U}$ 中。
如果是Library Files,會試圖把所有 ${U}$ 中的符號與 Library Files 中的符號匹配,匹配上了就從 ${U}$ 放入 ${D}$ 中。並把匹配上的 Module 放入 ${E}$ 中。一直重複直到 ${U}$、${D}$ 不再變化。Library Files剩下的內容直接就不管了。
如果往 ${D}$ 中放入了一個已經存在的符號或者掃描完所有文件後 ${U}$ 還是非空,則連結器會停止並報錯。否則將 ${E}$ 中內容經過重定址後合併,生成可執行文件。
深入理解计算机系统
AArch64 relocation prefixes?